﻿/*
    类 说 明：业务逻辑类，封装了数据表相关基本操作
	生成时间：2021/4/16 16:24:02
	生成工具：Kalman Studio
*/

using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Threading.Tasks;

using FreeSql;
using Kalman;
using Kalman.Extensions;
using Newtonsoft.Json.Linq;

namespace QuDao
{
    /// <summary>
    /// 数据表base_area关联的业务对象，处理该表相关的业务逻辑
    /// </summary>
    public sealed partial class AreaBO : SingletonBase<AreaBO>
    {
        readonly IFreeSql fsql;
        List<Area> list;
        List<Area> provinceList;
        List<Area> cityList;

        public AreaBO() : base()
        {
            fsql = ServiceLocator.Instance.GetRequiredService<IFreeSql>();
            Reload();
        }

        /// <summary>
        /// 获取省份列表
        /// </summary>
        public List<Area> ProvinceList { get { return provinceList; } }

        /// <summary>
        /// 获取城市列表
        /// </summary>
        public List<Area> CityList { get { return cityList; } }

        /// <summary>
        /// 重新加载数据到缓存
        /// </summary>
        public void Reload()
        {
            list?.Clear();
            provinceList?.Clear();
            cityList?.Clear();

            //list = dao.GetList<Area>(new int[] { 1, 2, 3 }, 1, 10000).ToList();//获取省市县四级数据
            list = fsql.Select<Area>().ToList();
            provinceList = list.FindAll(p => p.AreaLevel == 1);
            cityList = list.FindAll(p => p.AreaLevel == 2);
        }

        /// <summary>
        /// 更新行政区域指定的数据项缓存
        /// </summary>
        public void ReloadItem(int areaID)
        {
            var item = list.Find(p => p.AreaID == areaID);
            item = GetItem(areaID, true);//从数据库获取最新数据
        }

        /// <summary>
        /// 获取行政区域列表
        /// </summary>
        /// <param name="areaLevel">行政区域级别：1-省/直辖市/自治区，2-地/市，3-县/区，4-乡镇</param>
        /// <returns></returns>
        public List<Area> GetListByLevel(int areaLevel)
        {
            var result = list.FindAll(p => p.AreaLevel == areaLevel);
            return result.OrderByDescending(p => p.SortFlag).ToList();
        }

        public Area GetItem(int areaID, bool isFromDB = false)
        {
            if (isFromDB)
            {
                var item = GetItem<Area>(areaID);
                return item;
            }
            else
            {
                var item = list.FirstOrDefault(p => p.AreaID == areaID);
                return item;
            }
        }

        /// <summary>
		/// 获取下级行政区域列表
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="parentID">上级ID</param>
		/// <returns></returns>
		public IEnumerable<T> GetChildListFromDB<T>(int parentID)
        {
            var areaList = fsql.Select<Area>().Where(a => a.ParentID == parentID).OrderByDescending(a => a.SortFlag).ToList<T>();
            return areaList;
        }

        /// <summary>
        /// 获取行政区域列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="levels"></param>
        /// <param name="top"></param>
        /// <returns></returns>
        public IEnumerable<T> GetListFromDB<T>(int[] levels, int top)
        {
            var areaList = fsql.Select<Area>()
                .Where(a => levels.Contains(a.AreaLevel))
                .OrderByDescending(a => a.SortFlag)
                .Page(1, top).ToList<T>();
            return areaList;
        }

        /// <summary>
        /// 用于给城市下来控件提供树形数据源
        /// </summary>
        public List<Area> GetCityTreeList()
        {
            var result = list.FindAll(p => p.AreaLevel <= 2);
            return result.OrderByDescending(p => p.SortFlag).ToList();
        }

        /// <summary>
        /// 获取指定省份的城市列表
        /// </summary>
        /// <param name="provinceID"></param>
        /// <returns></returns>
        public List<Area> GetCityList(int? provinceID)
        {
            if (provinceID == null)
            {
                return cityList.OrderByDescending(p => p.SortFlag).ToList();
            }
            else
            {
                var result = cityList.FindAll(p => p.ParentID == provinceID);
                return result.OrderByDescending(p => p.SortFlag).ToList();
            }
        }

        /// <summary>
        /// 查询地区列表
        /// </summary>
        /// <param name="provinceID">省份ID</param>
        /// <param name="keyword">查询关键字</param>
        /// <returns></returns>
        public List<Area> Query(int provinceID, string keyword)
        {
            if (string.IsNullOrWhiteSpace(keyword))
            {
                var result = list.FindAll(p => p.AreaID > provinceID && p.AreaID < provinceID + 10000);
                return result.OrderByDescending(p => p.SortFlag).ToList();
            }
            else
            {
                var result = list.FindAll(p => p.AreaID > provinceID && p.AreaID < provinceID + 10000
                    && (p.AreaName.Contains(keyword) || p.AreaID.ToString().Contains(keyword) || p.ShortSpell.Contains(keyword)));
                return result.OrderByDescending(p => p.SortFlag).ToList();
            }
        }

        /// <summary>
        /// 获取指定省份的城市列表
        /// </summary>
        /// <param name="provinceName"></param>
        /// <returns></returns>
        public List<Area> GetCityList(string provinceName)
        {
            Area province = provinceList.Find(p => p.AreaLevel == 1 && p.AreaName == provinceName);

            if (province == null) return new List<Area>();

            return GetCityList(province.AreaID);
        }

        /// <summary>
        /// 获取已开通城市列表
        /// </summary>
        /// <returns></returns>
        public List<Area> GetEnableCityList()
        {
            var result = cityList.FindAll(p => p.IsEnable == true);
            return result.OrderByDescending(p => p.SortFlag).ToList();
        }

        public Area GetCity(int cityID)
        {
            return CityList.FirstOrDefault(p => p.AreaID == cityID);
        }

        /// <summary>
        /// 获取县市列表
        /// </summary>
        /// <param name="cityID"></param>
        /// <returns></returns>
        public List<Area> GetCountyList(int cityID)
        {
            if(cityID == 0)return new List<Area>();

            var result = list.FindAll(p => p.ParentID == cityID && p.AreaLevel == 3);
            return result.OrderByDescending(p => p.SortFlag).ToList();
        }

        /// <summary>
        /// 获取县市列表
        /// </summary>
        /// <param name="cityName"></param>
        /// <returns></returns>
        public List<Area> GetCountyList(string cityName)
        {
            var city = GetCity(cityName);

            if (city != null)
            {
                return GetCountyList(city.AreaID);
            }
            else
            {
                return new List<Area>();
            }
        }

        /// <summary>
        /// 查询城市
        /// </summary>
        /// <param name="keyword"></param>
        /// <returns></returns>
        public List<Area> QueryCity(string keyword)
        {
            var result = cityList.FindAll(p => p.AreaName.StartsWith(keyword) || p.ShortSpell.StartsWith(keyword));
            return result.OrderByDescending(p => p.SortFlag).ToList();
        }

        /// <summary>
        /// 根据城市名称匹配城市
        /// </summary>
        /// <param name="cityName"></param>
        /// <returns></returns>
        public Area MatchCity(string cityName)
        {
            var result = cityList.Find(p => p.AreaName.Contains(cityName));
            return result;
        }

        public Area GetArea(int areaID)
        {
            if (areaID < 100000 || areaID > 999999) return null;

            var result = list.Find(p => p.AreaID == areaID);
            return result;
        }

        public Area GetProvince(int provinceID)
        {
            return ProvinceList.FirstOrDefault(p => p.AreaID == provinceID);
        }

        /// <summary>
        /// 获取一级行政区域（省、直辖市、自治区）信息
        /// </summary>
        /// <param name="provinceName"></param>
        /// <returns></returns>
        public Area GetProvince(string provinceName)
        {
            var result = cityList.Find(p => p.AreaLevel == 1 && p.AreaName == provinceName);
            return result;
        }

        /// <summary>
        /// 获取二级行政区域（城市、地级市）信息
        /// </summary>
        /// <param name="cityName"></param>
        /// <returns></returns>
        public Area GetCity(string cityName)
        {
            var result = cityList.Find(p => p.AreaLevel == 2 && p.AreaName == cityName);
            return result;
        }

        ///// <summary>
        ///// 获取二级行政区域（区、县、县级市）信息
        ///// </summary>
        ///// <param name="cityName"></param>
        ///// <param name="districtName"></param>
        ///// <returns></returns>
        //public Area GetArea(string cityName, string districtName)
        //{
        //    Area city = GetCity(cityName);
        //    if (city == null) return null;

        //    var result = list.Find(p => p.ParentID == city.AreaID && p.AreaName == districtName);
        //    return result;
        //}

        /// <summary>
        /// 根据ID组，获取区域列表
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public List<Area> GetList(List<int> ids)
        {
            return list.FindAll(p => ids.Contains(p.AreaID)).OrderByDescending(p => p.SortFlag).ToList();
        }

        /// <summary>
        /// 获取省和市
        /// </summary>
        /// <returns></returns>
        public List<Area> GetList()
        {
            return list.FindAll(p => p.AreaLevel == 1 || p.AreaLevel == 2).OrderByDescending(p => p.SortFlag).ToList();
        }

        /// <summary>
        /// 获取开通服务的区域列表（城市及区县）
        /// </summary>
        /// <returns></returns>
        public List<AreaDto> GetServiceArea()
        {
            var list = fsql.Select<Area>()
                .Where(a => a.AreaLevel > 1 && a.IsEnable == true)
                .OrderByDescending(a => a.SortFlag)
                .ToList<AreaDto>();
            return list;
        }


        #region Generate Code

        /// <summary>
        /// 获取单条数据
        /// </summary>
        public T GetItem<T>(int id)
        {
            var item = fsql.Select<Area>().Where(a => a.AreaID == id).ToOne<T>();
            return item;
        }

        /// <summary>
        /// 从base_area表中获取数据列表
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public IEnumerable<T> GetList<T>(int[] ids)
        {
            var list = fsql.Select<Area>().Where(a => a.AreaID.IsIn<int>(ids)).OrderByDescending(a => a.SortFlag).ToList<T>();
            return list;
        }

        /// <summary>
        /// 新增行政区域
        /// </summary>
        public int Add(Area entity)
        {
            if(entity.ParentID > 0)
            {
                var parent = GetItem<Area>(entity.ParentID) ?? throw new AppException($"上级行政区域不存在：{entity.ParentID}");
                entity.AreaLevel = parent.AreaLevel + 1;
            }
            else
            {
                entity.AreaLevel = 1;
            }

            if (string.IsNullOrEmpty(entity.ShortName)) entity.ShortName = entity.AreaName;
            return fsql.Insert(entity).ExecuteAffrows();
        }

        /// <summary>
        /// 修改行政区域
        /// </summary>
        public int Modify(Area dto)
        {
            var item = GetItem(dto.AreaID) ?? throw new AppException($"行政区域不存在：{dto.AreaID}");
            var update = fsql.Update<Area>(dto.AreaID);
            if (dto.AreaName != item.AreaName) update.Set(a => a.AreaName, dto.AreaName);
            if (dto.ShortName != item.ShortName) update.Set(a => a.ShortName, dto.ShortName);
            if (dto.ParentID != item.ParentID) update.Set(a => a.ParentID, dto.ParentID);
            if (dto.AreaLevel != item.AreaLevel) update.Set(a => a.AreaLevel, dto.AreaLevel);
            if (dto.FirstLetter != item.FirstLetter) update.Set(a => a.FirstLetter, dto.FirstLetter);
            if (dto.ShortSpell != item.ShortSpell) update.Set(a => a.ShortSpell, dto.ShortSpell);
            if (dto.SortFlag != item.SortFlag) update.Set(a => a.SortFlag, dto.SortFlag);
            if (dto.IsEnable != item.IsEnable) update.Set(a => a.IsEnable, dto.IsEnable);

            return update.ExecuteAffrows();
        }

        public int SetEnable(int id, bool isEnable)
        {
            return fsql.Update<Area>(id).Set(a => a.IsEnable, isEnable).ExecuteAffrows();
        }

        /// <summary>
        /// 从base_area表中删除数据
        /// </summary>
        /// <param name="idList">主键ID值列表</param>
        /// <returns>成功返回true，失败返回false</returns>
        public int Delete(int[] ids)
        {
            return fsql.Delete<Area>().Where(a => a.AreaID.IsIn(ids)).ExecuteAffrows();
        }

        /// <summary>
        /// 从base_area表中删除数据
        /// </summary>
        /// <param name="id">主键ID值</param>
        /// <returns>成功返回true，失败返回false</returns>
        public int Delete(int id)
        {
            var ids = new int[] { id };
            return Delete(ids);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        public PagingResult<T> Query<T>(PagingRequest req)
        {
            var select = fsql.Select<Area>();
            foreach (var item in req.FilterItems)
            {
                switch (item.Field)
                {
                    case "AreaID":
                        select.Where(a => a.AreaID == int.Parse(item.Value));
                        break;
                    case "AreaName":
                        select.Where(a => a.AreaName.Contains(item.Value));
                        break;
                    default:
                        break;
                }
            }

            if (!string.IsNullOrEmpty(req.SortExp))
            {
                select.OrderBy(req.SortExp);//自定义排序
            }
            else
            {
                select.OrderByDescending(a => a.SortFlag).OrderBy(a => a.AreaID);//默认排序
            }

            var sql = select.ToSql();

            var list = select.Count(out var total).Page(req.PageIndex, req.PageSize).ToList<T>();
            return new PagingResult<T>
            {
                PageIndex = req.PageIndex,
                PageSize = req.PageSize,
                Data = list,
                Total = (int)total
            };
        }

        public PagingResult<Area> Query(PagingRequest req)
        {
            return Query<Area>(req);
        }
        #endregion
    }
}
